package com.example.venue_reservation_service.service.impl;

import com.example.venue_reservation_service.domain.VeMessage;
import com.example.venue_reservation_service.domain.VeSession;
import com.example.venue_reservation_service.entity.ChatRequest;
import com.example.venue_reservation_service.mapper.VeMessageMapper;
import com.example.venue_reservation_service.mapper.VeSessionMapper;
import com.example.venue_reservation_service.service.ChatService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ChatServiceImpl implements ChatService {

    @Resource
    private VeSessionMapper sessionMapper;

    @Resource
    private VeMessageMapper messageMapper;
    @Value("${internai.api-url}")
    private String apiUrl;
    @Value("${internai.api-key}")
    private String apiKey;

    @Override
    @Transactional
    public void streamChatResponse(ChatRequest request, ServletOutputStream outputStream, HttpServletRequest httpRequest) {
        // 获取或创建会话
        VeSession session = getOrCreateSession(request.getSessionToken(), httpRequest);
        String sessionToken = session.getSessionToken();

        // 保存用户消息
        saveMessage(request.getContent(), "user", session.getId());

        // 构建完整对话历史
        List<Map<String, String>> messages = buildMessages(session.getId());

        // 调用第三方API
        streamApiResponse(messages, outputStream, sessionToken, session.getId());

        // 更新会话结束时间
        updateSessionEndTime(session);
    }

    private VeSession getOrCreateSession(String sessionToken, HttpServletRequest request) {
        if (sessionToken != null && !sessionToken.isEmpty()) {
            VeSession session = sessionMapper.selectBySessionToken(sessionToken);
            if (session != null) {
                return session;
            }
        }

        // 创建新会话
        VeSession newSession = new VeSession();
        newSession.setUserIp(request.getRemoteAddr());
        newSession.setStartTime(LocalDateTime.now());
        newSession.setSessionToken(UUID.randomUUID().toString());
        newSession.setTitle("New Chat");
        newSession.setUserId(1);
        sessionMapper.insert(newSession);
        return newSession;
    }

    private void saveMessage(String content, String sender, Integer sessionId) {
        VeMessage message = new VeMessage();
        message.setSessionId(sessionId);
        message.setContent(content);
        message.setSender(sender);
        message.setCreatedAt(LocalDateTime.now());

        messageMapper.insert(message);
    }

    private List<Map<String, String>> buildMessages(Integer sessionId) {
        List<VeMessage> history = messageMapper.selectMessagesBySessionId(sessionId);

        return history.stream().map(msg -> {
            Map<String, String> messageMap = new HashMap<>();
            messageMap.put("role", msg.getSender().equals("user") ? "user" : "assistant");
            messageMap.put("content", msg.getContent());
            return messageMap;
        }).collect(Collectors.toList());
    }

    private void streamApiResponse(List<Map<String, String>> messages,
                                   ServletOutputStream outputStream,
                                   String sessionToken,
                                   Integer sessionId) {

        StringBuilder assistantResponse = new StringBuilder();

        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(apiUrl);
            httpPost.setHeader("Authorization", "Bearer " + apiKey);
            httpPost.setHeader("Content-Type", "application/json");

            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", "internlm3-latest");
            requestBody.put("messages", messages);
            requestBody.put("temperature", 0.8);
            requestBody.put("top_p", 0.9);
            requestBody.put("stream", true);

            httpPost.setEntity(new StringEntity(new ObjectMapper().writeValueAsString(requestBody)));

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                InputStream contentStream = response.getEntity().getContent();
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(contentStream))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (line.startsWith("data: ")) {
                            String json = line.substring(6).trim();
                            if (json.equals("[DONE]")) break;

                            JsonNode data = new ObjectMapper().readTree(json);
                            JsonNode choices = data.path("choices");
                            if (!choices.isEmpty()) {
                                String chunk = choices.get(0).path("delta").path("content").asText();
                                if (!chunk.isEmpty()) {
                                    assistantResponse.append(chunk);
                                    outputStream.write(chunk.getBytes(StandardCharsets.UTF_8));
                                    outputStream.flush();
                                }
                            }
                        }
                    }
                }
            }

            // 保存助手回复
            if (!assistantResponse.isEmpty()) {
                saveMessage(assistantResponse.toString(), "assistant", sessionId);
            }

        } catch (Exception e) {
            throw new RuntimeException("API call failed", e);
        }
    }

    private void updateSessionEndTime(VeSession session) {
        session.setEndTime(LocalDateTime.now());
        sessionMapper.updateById(session);
    }
}